gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scwinlib/SCWinFile.cpp

    //Download by http://www.NewXing.com
/*
*	This file is part of the EMFexplorer projet.
*	Copyright (C) 2004 Smith Charles.
*
*	This library is free software; you can redistribute it and/or
*	modify it under the terms of the GNU Lesser General Public
*	License as published by the Free Software Foundation; either
*	version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*
*	Extension: for commercial use, apply the Equity Public License, which
*	adds to the normal terms of the GLPL a condition of donation to the author.
*   If you are interested in support for this source code,
*   contact Smith Charles <smith.charles@free.fr> for more information.
*/


#include "stdafx.h"
#include "SCWinFile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BOOL SCExistFile(LPCTSTR lpszFname)
{
	CFileStatus rStatus;
	if (CFile::GetStatus(lpszFname, rStatus ))
		return (!(rStatus.m_attribute & CFile::directory));
	return FALSE;
}

// Note: good for an existing file
BOOL SCIsWriteableFile(LPCTSTR lpszFname)
{
	CFileStatus rStatus;
	if (CFile::GetStatus(lpszFname, rStatus ))
		return (0==(rStatus.m_attribute & CFile::directory) &&
				0==(rStatus.m_attribute & CFile::readOnly));
	return FALSE;
}

BOOL SCIsWriteableMedia(LPCTSTR lpszFname)
{
	TCHAR drive[_MAX_DRIVE];
	CString strPath;
#if 1
	_tsplitpath(lpszFname, drive, NULL, NULL, NULL);
	strPath.Format(_T("%s\\"), drive);

	switch (GetDriveType(LPCTSTR(strPath)))
	{
	case DRIVE_FIXED:
		// we should check write permission. But NT ... (see below)
		return TRUE;

	case DRIVE_REMOTE:
		// unfortunately, we don't have a DRIVE_REMOTE_CDROM flag
		// TODO:
		return FALSE;

	case DRIVE_CDROM:
	case DRIVE_REMOVABLE:
	default:
		break;
	}
	return FALSE;
#else
	// in Windows NT, all directories have read and write access
	// So, this won't work
	TCHAR dir[_MAX_DIR];
	_tsplitpath(lpszFname, drive, dir, NULL, NULL);
	strPath.Format(_T("%s%s"), drive, dir);
	CFileStatus rStatus;
	// GetStatus fails on directory names containing a trailing backslash
	if (strPath.Right(1)==_T('\\'))
		strPath = strPath.Left(strPath.GetLength() - 1);
	if (CFile::GetStatus(strPath, rStatus ))
		return (!(rStatus.m_attribute & CFile::readOnly));
	return FALSE;
#endif
}

// temporary dirname with trailing backslash, and using strSubdir
BOOL SCGetFullTempDirName(CString & strFinalDir, const CString & strSubdir, DWORD *pErrorCode/*=NULL*/)
{
	strFinalDir = _T("");
	DWORD dwResult = ::GetTempPath(MAX_PATH, strFinalDir.GetBuffer(MAX_PATH));
	if (pErrorCode)
		*pErrorCode = ::GetLastError();
	strFinalDir.ReleaseBuffer();

	if (dwResult)
	{
		if (strFinalDir.Right(1) != _T("\\"))
			strFinalDir += _T("\\");
		if (!strSubdir.IsEmpty())
		{
			strFinalDir += strSubdir;
			if (strFinalDir.Right(1)!=_T("\\"))
				strFinalDir += _T("\\");
		}
		return TRUE;
	}

	return FALSE;
}

///
/// Splitpath with support for UNC
///
void SCSplitPath(LPCTSTR szPath, LPTSTR szDrive, LPTSTR szDir, LPTSTR szFile, LPTSTR szExt)
{
	ASSERT(szPath);
	
	TCHAR drive[SC_MAX_UNC_DRIVE];
	TCHAR dir[_MAX_DIR];
	TCHAR fname[_MAX_FNAME];
	TCHAR ext[_MAX_EXT];
	if (!szDrive)
		szDrive = drive;
	if (!szDir)
		szDir = dir;
	if (!szFile)
		szFile = fname;
	if (!szExt)
		szExt = ext;

	BOOL bUNC = FALSE;
	TCHAR  *szVolume = _tcspbrk(szPath, _T(":\\/"));
	if (szVolume)
	{
		switch (*szVolume)
		{
		case _T('\\'):
			if (_T('\\') == *(++szVolume))
				bUNC = TRUE; // using UNC
			break;
			
		case _T('/'):
			if (_T('/') == *(++szVolume))
				bUNC = TRUE; // using UNC 
			break;
			
		case _T(':'):
			// using drive letter
			break;
			
		default:
			ASSERT(0);
		}
	}

	if (bUNC)
	{
		szVolume = _tcspbrk(++szVolume, _T("\\/")); // server

		ASSERT(szVolume);
		szVolume = _tcspbrk(++szVolume, _T("\\/"));	// share
		
		ASSERT(szVolume);
		_tsplitpath(szVolume, NULL, szDir, szFile, szExt);

		int iCount = szVolume - szPath;

		ASSERT(iCount<SC_MAX_UNC_DRIVE);
		_tcsncpy(szDrive, szPath, iCount);
		szDrive[iCount] = _T('\0');
	} else
	{
		_tsplitpath(szPath, szDrive, szDir, szFile, szExt);
	}
}

///
/// Create a subdirectory tree under the given directory
/// (we miss a CreateDirectoryTree function)
///
BOOL SCCreateDir(const TCHAR *szConstDir, DWORD *pErrorCode/*=NULL*/)
{
	ASSERT(szConstDir);
	if (!szConstDir)
		return FALSE;

	DWORD dwErrorCode = 0;

	//make a local copy to avoid problems
	int sLen = _tcslen(szConstDir);
	TCHAR *szDir = new TCHAR[sLen+1];
	_tcscpy(szDir, szConstDir);
	//now let's make the parse stuff

	// pass the volume (<drive letter>:\), or UNC name (\\server\share\)
	BOOL bUNC = FALSE;
	TCHAR  *szSubDir = _tcspbrk(szDir, _T(":\\/"));
	if (szSubDir)
	{
		switch (*szSubDir)
		{
		case _T('\\'):
			if (_T('\\') == *(++szSubDir))
				bUNC = TRUE; // using UNC
			break;
			
		case _T('/'):
			if (_T('/') == *(++szSubDir))
				bUNC = TRUE; // using UNC 
			break;
			
		case _T(':'):
			// using drive letter
			szSubDir++;
			break;
			
		default:
			ASSERT(0);
		}
	}

	if (bUNC)
	{
		szSubDir = _tcspbrk(++szSubDir, _T("\\/")); // server
		ASSERT(szSubDir);

		szSubDir = _tcspbrk(++szSubDir, _T("\\/"));	// share
		ASSERT(szSubDir);
	}

	//skip the root dir
	ASSERT(*szSubDir==_T('\\') || *szSubDir==_T('/'));
	szSubDir++;

	// create sub dirs
	BOOL bDir = TRUE;
	for (; (*szSubDir); szSubDir++)
	{
		switch(*szSubDir)
		{
		case _T('\\'): // take the left part and create a subdir
		case _T('/'):
			*szSubDir = _T('\0');
			bDir = ::CreateDirectory(szDir, NULL);
			// if dir already exists, continue
			if (!bDir)
			{
				bDir = ((dwErrorCode = ::GetLastError()) == ERROR_ALREADY_EXISTS);
				if (!bDir)
					goto clean_exit;
			}
			*szSubDir = _T('\\');
			break;
		}
	}
	// if there is no trailing \, create leaf subdir
	szSubDir--;
	if (bDir && *szSubDir!=_T('\\') && *szSubDir!=_T('/'))
	{
		bDir = ::CreateDirectory(szDir, NULL);
		if (!bDir)
			bDir = ((dwErrorCode = ::GetLastError()) == ERROR_ALREADY_EXISTS);
	}

clean_exit:
	//clean up
	delete [] szDir;
	if (pErrorCode)
		*pErrorCode = (dwErrorCode != ERROR_ALREADY_EXISTS) ?  dwErrorCode : 0;

	return bDir;
}

BOOL SCCreateTempDir(CString & strFinalDir, const CString & strSubdir, DWORD *pErrorCode/*=NULL*/)
{
	if (::SCGetFullTempDirName(strFinalDir, strSubdir, pErrorCode))
		return ::SCCreateDir(strFinalDir,pErrorCode);

	return FALSE;
}

#define SC_LITTLE_FROM_BIG_DW(p) \
			(DWORD)((*(p)<<24) + (*(p+1)<<16) + (*(p+2)<<8) + *(p+3))

#define SC_LITTLE_FROM_BIG_US(p) \
			(USHORT)((*(p)<<8)  + *(p+1))

#define SC_TTFILE_HEADERSIZE		(sizeof(FIXED) + 4*sizeof(USHORT))
#define SC_TTFILE_MINTABLES			10
#define SC_TTFILE_TBLENTRYSIZE		(4*sizeof(ULONG))
#define SC_TTFILE_MINSIZE			(SC_TTFILE_HEADERSIZE + SC_TTFILE_MINTABLES*SC_TTFILE_TBLENTRYSIZE) 

///
/// Tell if a font file may be TrueType (CreateScalableFontResource is more reliable)
///
BOOL SCIsTrueTypeFontFile(LPCTSTR lpszFilename)
{
	BOOL bTT = FALSE;
	LPBYTE pBytes = SCReadFileBytes(lpszFilename, SC_TTFILE_MINSIZE);
	if (pBytes)
	{
		DWORD dw = SC_LITTLE_FROM_BIG_DW(pBytes);
		// sfnt version==1.0
		bTT = (SC_LITTLE_FROM_BIG_DW(pBytes) == 0x00010000UL);
		if (bTT)
		{// at leat the required tables must exist
			USHORT usNbTables = SC_LITTLE_FROM_BIG_US(pBytes + sizeof(FIXED));
			bTT = (usNbTables>=SC_TTFILE_MINTABLES);
		}
		delete [] pBytes;
	}
	return bTT;
}

///
/// Return a buffer containing dwCount bytes read from the begining of a file
///
LPBYTE SCReadFileBytes(LPCTSTR lpszFname, DWORD dwCount, DWORD* pErrorCode/*=NULL*/)
{
	LPBYTE pBytes = NULL;
	UINT uiMode = SetErrorMode(SEM_FAILCRITICALERRORS);
	// Open the file for reading. 
    HANDLE hFile = CreateFile(lpszFname, GENERIC_READ, FILE_SHARE_READ, NULL,  
                        OPEN_EXISTING, 0, 0); 
    if (hFile == INVALID_HANDLE_VALUE)
	{
		if (pErrorCode)
			*pErrorCode = GetLastError();
	} else
	{
		pBytes = new BYTE[dwCount];
		if (pBytes)
		{
			DWORD dwRead;
			if (!ReadFile(hFile, pBytes, dwCount, &dwRead, NULL) || dwRead<dwCount)
			{
				if (pErrorCode)
					*pErrorCode = GetLastError();
				delete [] pBytes;
				pBytes = NULL;
			}
		}
		CloseHandle(hFile);
	}

	SetErrorMode(uiMode);
	return pBytes;
}

BOOL SCRemoveFileAttributes(LPCTSTR lpszFilename, DWORD dwAttrsToRemove)
{
	DWORD dwAttributes = GetFileAttributes(lpszFilename);
	return SetFileAttributes(lpszFilename, dwAttributes & ~dwAttrsToRemove);
}